
#include <iostream>
#include <memory>
#include <string>

using namespace std;

// 产品类
class Computer
{
public:
    void setboard(const string &board) { _board = board; }
    void setdisplay(const string &display) { _display = display; }
    void setOS(const string &OS) { _OS = OS; }
    void show()
    {
        cout << "电脑主板：" << _board << endl;
        cout << "电脑显示器：" << _display << endl;
        cout << "电脑系统：" << _OS << endl;
    }

protected:
    string _board;
    string _display;
    string _OS;
};

// 抽象建造者：需要把每一个零件建造出来，然后再建造电脑
class ComputerBuilder
{
public:
    virtual void buildboard(const string& board) = 0;
    virtual void builddisplay(const string& display) = 0;
    virtual void buildOS(const string& OS) = 0;
    virtual shared_ptr<Computer> build() = 0;
};

// 具体建造者：高性能电脑
class GamingComputerBuilder : public ComputerBuilder
{
public:
    GamingComputerBuilder() : _computer(make_shared<Computer>()) {}

    void buildboard(const string& board) override
    {
        _computer->setboard(board);
    }
    void builddisplay(const string& display) override
    {
        _computer->setdisplay(display);
    }
    void buildOS(const string& OS) override
    {
        _computer->setOS(OS);
    }
    // 建造一个电脑出来
    shared_ptr<Computer> build()
    {
        return _computer;
    }
private:
    shared_ptr<Computer> _computer;
};

// 指挥者：提供给调⽤者使⽤，通过指挥者来构造复杂产品
class Director
{
public:
    // 指挥者肯定是指挥建造者构建；所以传一个建造者
    Director(shared_ptr<ComputerBuilder> builder):_builder(builder){}
    // 指挥建造的顺序
    void construct(const string& board, const string& display, const string& OS)
    {
        _builder->buildboard(board);
        _builder->builddisplay(display);
        _builder->buildOS(OS);
    }
private:
    shared_ptr<ComputerBuilder> _builder;
};
int main()
{
    shared_ptr<ComputerBuilder> builder = make_shared<GamingComputerBuilder>();
    //ComputerBuilder* builder = new GamingComputerBuilder();

    unique_ptr<Director> director(new Director(builder));
    //指挥者指挥建造好各个零件
    director->construct("英特尔主板", "三星显示器", "MacOS");
    //然后建造者才能建造出电脑
    shared_ptr<Computer> computer = builder->build();
    computer->show();
    return 0;
}